/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "kh_sle_host.h"
#include "kh_sle_connect.h"
#include "sle_connect_hal.h"
#include "sle_connect_config.h"
#include "sle_hilog.h"
#include "sle_lite_advance_setting.h"
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <cmsis_os2.h>

#ifndef ServiceCallbackNumFlag
#define ServiceCallbackNumFlag
#define serviceCallbackNum  3
#endif  // ServiceCallbackNumFlag
static bool g_isConnectServiceInit = false;
static SleConnectCallbacks* g_connectCbs[serviceCallbackNum] = {NULL};
static SleConnectHalCallbacks* g_connectHalCbs = NULL;
static osMutexId_t g_connectCbMuxHandle;
static osSemaphoreId_t g_sleConnectSemHandle;
static SleErrorCode g_sleConnectAsyncRet = SLE_ERR_UNKNOWN;
static uint32_t SleConnectTimeOut = 3000;
static uint16_t g_connectNumber = 0;
static SleConnectDev g_connectdevList[SLE_MAX_CONNECT_ID_NUM];

static SleConnectModeConfig g_default_connect_work_mode;
static SleConnectConfig g_default_connect_config;
static SleDefaultConnectionParam g_default_connect_param;

void AddConnectDevToList(uint16_t connectId, SleDeviceAddress *addr)
{
    if(CheckIsConnected(connectId) == SLE_NO_ERROR) return;
    for(int i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        if(g_connectdevList[i].connId == 0xF) {
            g_connectdevList[i].connId = connectId;
            memcpy(&g_connectdevList[i].addr, addr, sizeof(SleDeviceAddress));
            g_connectNumber++;
            return;
        }
    }
    SLE_LOGE("AddConnectDevToList failed");
}

void RemoveConnectIdFromList(uint16_t connectId)
{
    if(CheckIsConnected(connectId) != SLE_NO_ERROR) return;
    for(int i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        if(g_connectdevList[i].connId == connectId) {
            g_connectdevList[i].connId = 0xF;
            g_connectNumber--;
            return;
        }
    }
    SLE_LOGE("RemoveConnectIdFromList failed");
}

void NotifySleConnectStateChange(uint16_t connectId, const SleDeviceAddress *addr
        , SleConnectState connectState, SlePairState pairState, SleDisConnectReason discReason)
{
    SLE_LOGD("NotifySleConnectStateChange("MACSTR") connectId(%d) SleConnectState(%d) SleDisConnectReason(%d)", MAC2STR(addr->addr), connectId, connectState, discReason);
    if(connectState == SLE_CONNECT_CONNECTED_STATE) {
        AddConnectDevToList(connectId, addr);
    } else if(connectState == SLE_CONNECT_DISCONNECTED_STATE) {
        RemoveConnectIdFromList(connectId);
        RemoveRecomSendDataToMap(connectId);
        if (pairState != SLE_PAIR_NONE_STATE) {
            RemovePair(addr);
        }
    }
    SleDeviceAddress addrCb;
    memcpy(&addrCb, addr, sizeof(SleDeviceAddress));
    for(int i = 0; i < serviceCallbackNum; i++) {
        if(g_connectCbs[i] != NULL && g_connectCbs[i]->OnSleConnStateChangeCb != NULL) {
            g_connectCbs[i]->OnSleConnStateChangeCb(connectId, &addrCb, connectState, pairState, discReason);
        }
    }
}

uint16_t CalculateConnInterval(uint16_t stepCount, uint16_t stepPeriod, uint16_t devNum)
{
    uint16_t res = 0;
    res = (uint16_t)(stepPeriod * pow(2, (double)devNum / stepCount)) +
          (uint16_t)((stepPeriod / 2) * (devNum % stepCount) * (devNum - 1)) - (devNum * devNum);
    return res;
}

SleErrorCode CalculateConnParam(SleConnectionParamUpdate *param, uint16_t connectNum)
{
    param->intervalMin = CalculateConnInterval(g_default_connect_work_mode.stepCount, g_default_connect_work_mode.stepPeriod, connectNum);
    param->intervalMax = param->intervalMin;
    param->maxLatency = 0;
    param->supervisionTimeout = 500;
    SLE_LOGD("the CalculateConnParam is %{public}d", param->intervalMin);
    return SLE_NO_ERROR;
}

SleErrorCode SetDefaultConnParam()
{
    SLE_LOGD("SetDefaultConnParam in");
    SleConnectDev connectDevList[SLE_MAX_CONNECT_ID_NUM]; // 最多有20个连接
    uint16_t connectNum = SLE_MAX_CONNECT_ID_NUM;
    SleErrorCode result = GetConnectDevList(connectDevList, &connectNum);
    SLE_ASSERT_AND_RETURN_RET(result == SLE_NO_ERROR, result);
    SLE_ASSERT_AND_RETURN_RET(connectNum != 0, SLE_ERR_FAILED);

    SleConnectionParamUpdate updateParam;
    SleErrorCode ret = CalculateConnParam(&updateParam, connectNum);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, SLE_ERR_FAILED, "CalculateConnParam failed!");

    SleDefaultConnectionParam defaultConnParam = {0};
    defaultConnParam.min_interval = updateParam.intervalMin;
    defaultConnParam.max_interval = updateParam.intervalMax;
    defaultConnParam.enable_filter_policy = g_default_connect_param.enable_filter_policy;
    defaultConnParam.initiate_phys = g_default_connect_param.initiate_phys;
    defaultConnParam.gt_negotiate = g_default_connect_param.gt_negotiate;
    defaultConnParam.scan_interval = g_default_connect_param.scan_interval;
    defaultConnParam.scan_window = g_default_connect_param.scan_window;
    defaultConnParam.timeout = g_default_connect_param.timeout;

    ret = SleConnectHalSetDefaultConnParam(&defaultConnParam);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, ret, "SetDefaultConnParam failed(%{public}d)!", ret);
}

void OnSleConnectHalConnectStateChange(uint16_t connectId, const SleDeviceAddress *addr
        , SleAcbState connState, SlePairState pairState, SleDisConnectReason discReason)
{
    SLE_LOGD("OnSleConnectHalConnectStateChange("MACSTR") connectId(%d) SleConnectState(%d) SleDisConnectReason(%d)", MAC2STR(addr->addr), connectId, connState, discReason);
    SleConnectState connectState = (SleConnectState)connState;
    NotifySleConnectStateChange(connectId, addr, connectState, pairState, discReason);
    // SetDefaultConnParam();
}

void OnSleConnectHalConnectParamUpdateReq(uint16_t connectId, SleHalErrorCode errCode, const SleConnectParam *connectParam)
{
    SLE_LOGD("OnSleConnectHalConnectParamUpdateReq connectId(%d) errCode(%d)", connectId, errCode);
}

void OnSleConnectHalConnectParamUpdateComplete(uint16_t connectId, SleHalErrorCode errCode, const SleConnectionParamUpdateEvt *connectParam)
{
    SLE_LOGD("OnSleConnectHalConnectParamUpdateComplete connectId(%d) errCode(%d) param(interval(%d),latency(%d),timeout(%d))"
        , connectId, errCode, connectParam->interval, connectParam->latency, connectParam->supervisionTimeout);
    SleConnectionParamUpdateEvt connectParamCb;
    memcpy(&connectParamCb, connectParam, sizeof(SleConnectionParamUpdateEvt));
    for(int i = 0; i < serviceCallbackNum; i++) {
        if(g_connectCbs[i] != NULL && g_connectCbs[i]->OnSleConnParamUpdatedCb != NULL) {
            g_connectCbs[i]->OnSleConnParamUpdatedCb(connectId, (SleErrorCode)errCode, &connectParamCb);
        }
    }
    g_sleConnectAsyncRet = (SleErrorCode)errCode;
}

void OnSleConnectHalAuthComplete(uint16_t connectId, const SleDeviceAddress *addr, SleHalErrorCode errCode, const SleAuthInfo *authInfo)
{
    SLE_LOGD("OnSleConnectHalAuthComplete("MACSTR") connectId(%d) errCode(%d)", MAC2STR(addr->addr), connectId, errCode);
}

void OnSleConnectHalPairComplete(uint16_t connectId, const SleDeviceAddress *addr, SleHalErrorCode errCode)
{
    SLE_LOGD("OnSleConnectHalPairComplete("MACSTR") connectId(%d) errCode(%d)", MAC2STR(addr->addr), connectId, errCode);
    SLE_ASSERT_AND_PRINT_LOG(errCode == SLE_HAL_SUCCESS, "pair failed(%hhu)", errCode);
    SlePairState pairState = (errCode == SLE_HAL_SUCCESS) ? SLE_PAIR_PAIRED_STATE : SLE_PAIR_ERROR_STATE;
    NotifySleConnectStateChange(connectId, addr, SLE_CONNECT_CONNECTED_STATE, pairState, SLE_CONNECT_OR_DISCONNECT_SUCCESS);
}

void OnSleConnectHalReadRssiComplete(uint16_t connectId, int8_t rssi, SleHalErrorCode errCode)
{
    SLE_LOGD("OnSleConnectHalReadRssiComplete connectId(%d) errCode(%d) rssi(%d)", connectId, errCode, rssi);
    g_sleConnectAsyncRet = (SleErrorCode)errCode;
    osSemaphoreRelease(g_sleConnectSemHandle);
}

void OnSleConnectHalSetPhyParamComplete(uint16_t connectId, SleHalErrorCode errCode, const SleConnectionPhyParam *param)
{
    SLE_LOGD("OnSleConnectHalSetPhyParamComplete connectId(%d) errCode(%d) phy(%d)", connectId, errCode, param->rx_phy);
    g_sleConnectAsyncRet = (SleErrorCode)errCode;
    SleConnectHalSetMcsValue(connectId, g_default_connect_config.mcs);
}

SleErrorCode GetConnectWorkConfig(SleConnectModeConfig *workConnParam)
{
    SLE_ASSERT_AND_RETURN_RET(workConnParam != NULL, SLE_ERR_INVALID_PARAM);
    uint16_t realLen = 0;
    uint8_t data[SLE_NV_CONNECT_CONFIG_MODE_DATA_LEN] = {0};
    SleErrorCode ret = SleUapiNvRead(SLE_NV_CONNECT_ID, SLE_NV_CONNECT_ID_DATA_LEN, &realLen, data);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    uint8_t pos = 0;
    workConnParam->workMode = *(data + pos);
    pos += sizeof(uint8_t);
    workConnParam->stepCount = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    workConnParam->stepPeriod = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    workConnParam->configMode = *(data + pos);
    pos += sizeof(uint8_t);
    return SLE_NO_ERROR;
}

SleErrorCode SleConvertByteToSleDefaultConnectConfig(uint8_t *data, SleDefaultConnectionParam *defaultConnParam)
{
    SLE_ASSERT_AND_RETURN_RET(data != NULL, SLE_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(defaultConnParam != NULL, SLE_ERR_INVALID_PARAM);
    uint8_t pos = 0;
    defaultConnParam->enable_filter_policy = *(data + pos);
    pos += sizeof(uint8_t);
    defaultConnParam->initiate_phys = *(data + pos);
    pos += sizeof(uint8_t);
    defaultConnParam->gt_negotiate = *(data + pos);
    pos += sizeof(uint8_t);
    defaultConnParam->scan_interval = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    defaultConnParam->scan_window = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    defaultConnParam->min_interval = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    defaultConnParam->max_interval = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    defaultConnParam->timeout = COMBINE_BYTS_16(*(data + pos), *(data + pos + 1));
    pos += sizeof(uint16_t);
    return SLE_NO_ERROR;
}

SleErrorCode GetDefaultConnectConfig(SleDefaultConnectionParam *defaultConnParam)//13
{
    SLE_ASSERT_AND_RETURN_RET(defaultConnParam != NULL, SLE_ERR_INVALID_PARAM);
    uint16_t realLen = 0;
    uint8_t data[SLE_NV_CONNECT_CONFIG_MODE_DATA_LEN] = {0};
    SleErrorCode ret = SleUapiNvRead(SLE_NV_DEFAULT_CONNECT_ID, SLE_NV_CONNECT_CONFIG_MODE_DATA_LEN, &realLen, data);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return SleConvertByteToSleDefaultConnectConfig(data, defaultConnParam);
}

SleErrorCode InitSleConnectService(void)
{
    SLE_LOGD("InitSleConnectService");
    SLE_ASSERT_AND_RETURN_RET(g_isConnectServiceInit == false, SLE_NO_ERROR);
    SleErrorCode ret = SLE_ERR_UNKNOWN;
    ret = InitSleConnectHal();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);

    if (g_connectCbMuxHandle == 0) {
      osMutexAttr_t attr = {
            .name = "sle_connect_mux",
        };
        g_connectCbMuxHandle = osMutexNew(&attr);
    }
    if (g_sleConnectSemHandle == 0) {
        g_sleConnectSemHandle = osSemaphoreNew(1, 0, NULL);
    }
    for (int i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        g_connectdevList[i].connId = 0xF;
    }
    InitSleRecommendSendSize();

    if(g_connectHalCbs == NULL) {
        g_connectHalCbs = (SleConnectHalCallbacks*)malloc(sizeof(SleConnectHalCallbacks));
        SLE_ASSERT_AND_RETURN_RET(g_connectHalCbs != NULL, SLE_ERR_SYSTEM_WRONG);
        g_connectHalCbs->OnConnectHalConnectStateChangeCb = OnSleConnectHalConnectStateChange;
        g_connectHalCbs->OnConnectHalConnectParamUpdateReqCb = OnSleConnectHalConnectParamUpdateReq;
        g_connectHalCbs->OnConnectHalConnectParamUpdateCompleteCb = OnSleConnectHalConnectParamUpdateComplete;
        g_connectHalCbs->OnConnectHalAuthCompleteCb = OnSleConnectHalAuthComplete;
        g_connectHalCbs->OnConnectHalPairCompleteCb = OnSleConnectHalPairComplete;
        g_connectHalCbs->OnConnectHalReadRssiCompleteCb = OnSleConnectHalReadRssiComplete;
        g_connectHalCbs->OnConnectHalSetPhyParamCompleteCb = OnSleConnectHalSetPhyParamComplete;
    }
    ret = (SleErrorCode)SleConnectHalRegisterCallbacks(g_connectHalCbs);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    g_sleConnectAsyncRet = SLE_ERR_UNKNOWN;
    g_isConnectServiceInit = true;
    ret = GetConnectWorkConfig(&g_default_connect_work_mode);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = GetHostDefaultConnectConfig(&g_default_connect_config);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = GetDefaultConnectConfig(&g_default_connect_param);
    return ret;
}

SleErrorCode CheckCanOprateConnect(void)
{
    SLE_ASSERT_AND_RETURN_RET(g_isConnectServiceInit == true, SLE_ERR_NOT_READY);
    SleDeviceState hostState;
    SleErrorCode ret = GetSleState(&hostState);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    SLE_ASSERT_AND_RETURN_RET(hostState == SLE_HOST_STATE_ENABLED, SLE_ERR_STATUS_WRONG);
    return SLE_NO_ERROR;
}

SleErrorCode DeinitSleConnectService(void)
{
    SLE_LOGD("DeinitSleConnectService");
    SleErrorCode ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = DeinitSleConnectHal();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);

    osMutexAcquire(g_connectCbMuxHandle, 0);
    if (g_connectCbMuxHandle == 0) {
        SLE_LOGW("g_connectCbMuxHandle is 0");
        return SLE_NO_ERROR;
    }
    osMutexRelease(g_connectCbMuxHandle);
    osMutexDelete(g_connectCbMuxHandle);
    g_connectCbMuxHandle = 0;
    osSemaphoreDelete(g_sleConnectSemHandle);
    g_sleConnectSemHandle = 0;
    g_sleConnectAsyncRet = SLE_ERR_UNKNOWN;
    g_isConnectServiceInit = false;
    return ret;
}

static SleErrorCode CheckIsDevConnected(const SleDeviceAddress *remoteAddr)
{
    SLE_ASSERT_AND_RETURN_RET(remoteAddr != NULL, SLE_ERR_INVALID_PARAM);
    for(int i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        if (memcmp(&g_connectdevList[i].addr, remoteAddr->addr, sizeof(SleDeviceAddress)) == 0 &&
            g_connectdevList[i].connId != 0xF) {
            return SLE_NO_ERROR;
        }
    }
    return SLE_ERR_FAILED;
}

static SleErrorCode CheckSleAddress(const SleDeviceAddress *address)
{
    if (address->addrType != SLE_PUBLIC_ADDRESS_TYPE && address->addrType != SLE_RANDOM_ADDRESS_TYPE) {
        SLE_LOGE("check address type error!");
        return SLE_ERR_INVALID_PARAM;
    }
    bool AllZero = true;
    bool AllFF = true;
    for (int i = 0; i < SLE_DEVICE_ADDRESS_LEN; ++i) {
        if (address->addr[i] != 0x00) {
            AllZero = false;
        }
        if (address->addr[i] != 0xFF) {
            AllFF = false;
        }
    }
    SLE_ASSERT_AND_RETURN_RET_LOG((!AllZero && !AllFF), SLE_ERR_INVALID_PARAM, "check address error!");
    return SLE_NO_ERROR;
}

static SleErrorCode CheckConnectParam(const SleConnectionParamUpdate *param)
{
    SLE_ASSERT_AND_RETURN_RET_LOG(param->intervalMin >= 0x000A && param->intervalMin <= 0x3E80,
        SLE_ERR_INVALID_PARAM, "param connect interval(%d) min error!", param->intervalMin);
    SLE_ASSERT_AND_RETURN_RET_LOG(param->intervalMax >= 0x000A && param->intervalMax <= 0x3E80,
        SLE_ERR_INVALID_PARAM, "param connect interval max error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param->intervalMin <= param->intervalMax,
        SLE_ERR_INVALID_PARAM, "param connect interval error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param->maxLatency <= 0x01F3,
        SLE_ERR_INVALID_PARAM, "param connect latency error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param->supervisionTimeout >= 0x000A && param->supervisionTimeout <= 0x0C80,
        SLE_ERR_INVALID_PARAM, "param connect supervision timeout error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param->maxLatency < param->supervisionTimeout,
        SLE_ERR_INVALID_PARAM, "param connect latency than supervisionTimeout error!");
    return SLE_NO_ERROR;
}

SleErrorCode SleConnect(const SleDeviceAddress *remoteAddr)
{
    SLE_ASSERT_AND_RETURN_RET(remoteAddr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    SLE_LOGD("SleConnect("MACSTR")", MAC2STR(remoteAddr->addr));
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = CheckIsDevConnected(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret != SLE_NO_ERROR, SLE_ERR_CONNECT_SUCCESS_WHEN_CONNECTED);
    ret = SleConnectHalConnect(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode SleDisconnect(const SleDeviceAddress *remoteAddr)
{
    SLE_ASSERT_AND_RETURN_RET(remoteAddr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    SLE_LOGD("SleDisconnect("MACSTR")", MAC2STR(remoteAddr->addr));
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = CheckIsDevConnected(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret != SLE_NO_ERROR, SLE_ERR_DISCONNECT_SUCCESS_WHEN_DISCONNECTED);
    ret = SleConnectHalDisconnect(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode SleUpdateConnParam(const SleConnectionParamUpdate *param)
{
    SLE_LOGD("SleUpdateConnParam and set phy");
    SLE_ASSERT_AND_RETURN_RET(param != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckConnectParam(param);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = CheckIsConnected(param->connectId);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    SleConnectionPhyParam phy_param = {0};
    phy_param.tx_phy = g_default_connect_config.phy;
    phy_param.rx_phy = g_default_connect_config.phy;
    phy_param.tx_format = g_default_connect_config.formatType;
    phy_param.rx_format = g_default_connect_config.formatType;
    phy_param.tx_pilot_density = g_default_connect_config.pilotDensity;
    phy_param.rx_pilot_density = g_default_connect_config.pilotDensity;
    phy_param.g_feedback = 0;
    phy_param.t_feedback = 0;
    ret = SleConnectHalSetPhyParam(param->connectId, &phy_param);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_HAL_SUCCESS, ret);

    ret = SleConnectHalUpdateConnParam(param);
    return ret;
}

SleErrorCode SleUpdateAllConnParam(SleConnectDev *successUpdateDevList, uint16_t *successUpdateNum)
{
    SLE_LOGD("SleUpdateAllConnParam in");
    SLE_ASSERT_AND_RETURN_RET(successUpdateDevList != NULL, SLE_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(successUpdateNum != NULL, SLE_ERR_INVALID_PARAM);
    SleConnectDev connectDevList[SLE_MAX_CONNECT_ID_NUM]; // 最多有20个连接
    uint16_t connectNum = SLE_MAX_CONNECT_ID_NUM;
    *successUpdateNum = 0;

    SleErrorCode result = GetConnectDevList(connectDevList, &connectNum);
    SLE_ASSERT_AND_RETURN_RET(result == SLE_NO_ERROR, result);
    SLE_ASSERT_AND_RETURN_RET(connectNum != 0, SLE_ERR_FAILED);
    SleConnectionParamUpdate param;
    result = CalculateConnParam(&param, connectNum);
    SLE_ASSERT_AND_RETURN_RET(result == SLE_NO_ERROR, result);

    for (uint16_t i = 0; i < connectNum; i++) {
        param.connectId = connectDevList[i].connId;
        result = SleUpdateConnParam(&param);
        if (result != SLE_NO_ERROR) {
            SLE_LOGE("update param connId[%{public}d] failed!", param.connectId);
            continue;
        }
        (*successUpdateNum)++;
        successUpdateDevList[i].connId = param.connectId;
        memcpy(&successUpdateDevList[i].addr, &connectDevList[i].addr, sizeof(SleDeviceAddress));
    }
    return SLE_NO_ERROR;
}

SleErrorCode SleGetRecomSendDataSize(uint16_t connectId, uint32_t *recomSendDataSize)
{
    SLE_ASSERT_AND_RETURN_RET(recomSendDataSize != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckIsConnected(connectId);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return GetRecomSendDataSizeAdvance(connectId, recomSendDataSize);
}

SleErrorCode SendPairReq(const SleDeviceAddress *remoteAddr)
{
    SLE_ASSERT_AND_RETURN_RET(remoteAddr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    SLE_LOGD("SendPairReq("MACSTR")", MAC2STR(remoteAddr->addr));
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = SleConnectHalSendPairReq(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode RemovePair(const SleDeviceAddress *remoteAddr)
{
    SLE_ASSERT_AND_RETURN_RET(remoteAddr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    SLE_LOGD("RemovePair("MACSTR")", MAC2STR(remoteAddr->addr));
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = SleConnectHalRemovePair(remoteAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode RemoveAllPairs(void)
{
    SLE_LOGD("RemoveAllPairs");
    SleErrorCode ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    ret = SleConnectHalRemoveAllPairs();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode GetDevicePairState(const SleDeviceAddress *addr, SlePairState *pairState)
{
    SLE_ASSERT_AND_RETURN_RET(addr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(addr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    SLE_LOGD("GetDevicePairState("MACSTR") state(%d)", MAC2STR(addr->addr), pairState);
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    uint16_t connectId = 0;
    ret = GetConnectDeviceId(addr, &connectId);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    SLE_ASSERT_AND_RETURN_RET(pairState != NULL, SLE_ERR_INVALID_PARAM);
    ret = SleConnectHalGetPairState(addr, pairState);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode ReadRemoteRssi(uint16_t connectId, int8_t *rssi)
{
    SLE_LOGD("ReadRemoteRssi connectId(%d)", connectId);
    SLE_ASSERT_AND_RETURN_RET(connectId < SLE_MAX_CONNECT_ID_NUM, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    CheckIsConnected(connectId);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    SLE_ASSERT_AND_RETURN_RET(rssi != NULL, SLE_ERR_INVALID_PARAM);
    ret = SleConnectHalReadRemoteRssi(connectId);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    osStatus_t uwRet = osSemaphoreAcquire(g_sleConnectSemHandle, SleConnectTimeOut);
    SLE_ASSERT_AND_RETURN_RET(uwRet != osErrorTimeout, SLE_ERR_TIME_OUT);
    ret = g_sleConnectAsyncRet;
    g_sleConnectAsyncRet = SLE_ERR_UNKNOWN;
    return ret;
}

SleErrorCode GetConnectDevList(SleConnectDev *connectDevList, uint16_t *connectNum)
{
    SLE_LOGD("GetConnectDeviceList");
    SLE_ASSERT_AND_RETURN_RET(connectDevList, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    memcpy_s(connectDevList, *connectNum * sizeof(SleConnectDev), g_connectdevList, sizeof(g_connectdevList));
    *connectNum = g_connectNumber;
    return SLE_NO_ERROR;
}

SleErrorCode GetConnectDeviceId(const SleDeviceAddress *remoteDeviceAddr, uint16_t *connectId)
{
    SLE_LOGD("GetConnectDeviceId");
    SLE_ASSERT_AND_RETURN_RET(remoteDeviceAddr != NULL, SLE_ERR_INVALID_PARAM);
    SleErrorCode ret = CheckSleAddress(remoteDeviceAddr);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM);
    ret = CheckCanOprateConnect();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    SLE_ASSERT_AND_RETURN_RET(connectId != NULL, SLE_ERR_INVALID_PARAM);
    for (int i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        int ret = memcmp(&g_connectdevList[i].addr, remoteDeviceAddr, sizeof(SleDeviceAddress));
        if (ret == 0) {
            *connectId = g_connectdevList[i].connId;
            return SLE_NO_ERROR;
        }
    }
    return SLE_ERR_FAILED;
}

SleErrorCode CheckIsConnected(uint16_t connectId)
{
    SleConnectDev connectDevList[SLE_MAX_CONNECT_ID_NUM];
    uint16_t connectNum = SLE_MAX_CONNECT_ID_NUM;
    GetConnectDevList(connectDevList, &connectNum);
    for(uint16_t i = 0; i < SLE_MAX_CONNECT_ID_NUM; i++) {
        if (connectId == connectDevList[i].connId) {
            return SLE_NO_ERROR;
        }
    }
    SLE_LOGW("connectId(%d) is not connected", connectId);
    return SLE_ERR_FAILED;
}

static bool CheckIsRegistered(const SleConnectCallbacks *connectCallbacks)
{
    for(uint8_t i = 0; i < serviceCallbackNum; i++) {
        if (g_connectCbs[i] == connectCallbacks) {
            return true;
        }
    }
    return false;
}

SleErrorCode RegisterConnectCallbacks(SleConnectCallbacks *connectCallbacks)
{
    SLE_LOGD("RegisterConnectCallbacks");
    SLE_ASSERT_AND_RETURN_RET(connectCallbacks != NULL, SLE_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(CheckIsRegistered(connectCallbacks) == false, SLE_NO_ERROR);
    SleErrorCode ret = SLE_ERR_UNKNOWN;
    uint8_t count = 0;
    osMutexAcquire(g_connectCbMuxHandle, 0);
    for(; count < serviceCallbackNum; count++) {
        if(g_connectCbs[count] == NULL) {
            g_connectCbs[count] = connectCallbacks;
            ret = SLE_NO_ERROR;
            break;
        }
    }
    osMutexRelease(g_connectCbMuxHandle);
    SLE_ASSERT_AND_RETURN_RET(count < serviceCallbackNum, SLE_ERR_NO_MEM);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}

SleErrorCode UnregisterConnectCallbacks(SleConnectCallbacks *connectCallbacks)
{
    SLE_LOGD("UnregisterConnectCallbacks");
    SLE_ASSERT_AND_RETURN_RET(g_isConnectServiceInit == true, SLE_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(connectCallbacks != NULL, SLE_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(CheckIsRegistered(connectCallbacks) == true, SLE_NO_ERROR);
    SleErrorCode ret = SLE_ERR_FAILED;
    osMutexAcquire(g_connectCbMuxHandle, 0);
    for(uint8_t i = 0; i < serviceCallbackNum; i++) {
        if (g_connectCbs[i] == connectCallbacks) {
            g_connectCbs[i] = NULL;
            ret = SLE_NO_ERROR;
            break;
        }
    }
    osMutexRelease(g_connectCbMuxHandle);
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_NO_ERROR, ret);
    return ret;
}
